package cn.sangyy.user.service.impl;

import cn.sangyy.basic.common.code.CodeEnum;
import cn.sangyy.basic.constent.BaseConstants;
import cn.sangyy.basic.constent.WxConstants;
import cn.sangyy.basic.exception.CarAssert;
import cn.sangyy.basic.utils.AjaxResult;
import cn.sangyy.basic.utils.HttpUtil;
import cn.sangyy.basic.utils.MD5Utils;
import cn.sangyy.user.domain.LoginInfo;
import cn.sangyy.user.domain.UserWx;
import cn.sangyy.user.dto.AccountLoginDto;
import cn.sangyy.user.dto.PhoneCodeLoginDto;
import cn.sangyy.user.mapper.LoginInfoMapper;
import cn.sangyy.user.mapper.UserWxMapper;
import cn.sangyy.user.service.ILoginService;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @author SangYY
 * @date: 2023/06/02/23:02
 */
@Service
public class LoginServiceImpl implements ILoginService {

    @Autowired
    private LoginInfoMapper loginInfoMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private UserWxMapper wxMapper;

    @Override
    @Transactional
    public Map<String, Object> accountLogin(AccountLoginDto dto) {
        String username = dto.getUsername();
        Integer type = dto.getType();
        List<LoginInfo> loginInfo = loginInfoMapper.selectList(new EntityWrapper<LoginInfo>()
                .eq("username",username).or().eq("phone",username)
                .or().eq("email",username).and().eq("type",type));
        //用户不存在
        CarAssert.assertListNotNull(loginInfo,CodeEnum.LOGIN_USERNAME_IS_ERROR);
        LoginInfo user = loginInfo.get(0);
        String salt = user.getSalt();
        String password = MD5Utils.encrypByMd5("car"+salt+"register"+dto.getPassword());
        //密码不等
        CarAssert.assertStrEquals(password,user.getPassword(),CodeEnum.LOGIN_USERNAME_IS_ERROR);
        String token = UUID.randomUUID().toString();
        redisTemplate.opsForValue().set(token,user,30, TimeUnit.MINUTES);
        Map<String,Object> result = new HashMap<>();
        result.put("token",token);
        result.put("loginUser",user);
        return result;
    }

    @Override
    public Map<String, Object> phoneCodeLogin(PhoneCodeLoginDto dto) {
        String phone = dto.getPhone();
        List<LoginInfo> users = loginInfoMapper.selectList(new EntityWrapper<LoginInfo>().eq("phone", phone));
        CarAssert.assertListNotNull(users,CodeEnum.REGISTER_PHONE_NOT_EXIST);
        String code = dto.getCode();
        String phoneKeyInRedis = BaseConstants.LOGIN_PHONE_CODE_IN_REDIS+phone;
        String phoneCode = (String) redisTemplate.opsForValue().get(phoneKeyInRedis);
        CarAssert.assertStrNotBlank(phoneCode,CodeEnum.REGISTER_PHONE_CODE_EXPIRED);
        CarAssert.assertStrEquals(code,phoneCode,CodeEnum.CODE_ERROR);
        LoginInfo loginInfo = users.get(0);
        HashMap<String, Object> result = backLoginInfo(loginInfo);
        return result;
    }

    public HashMap<String, Object> backLoginInfo(LoginInfo loginInfo) {
        String token = UUID.randomUUID().toString();
        redisTemplate.opsForValue().set(token, loginInfo,30,TimeUnit.MINUTES);
        HashMap<String, Object> result = new HashMap<>();
        result.put("token",token);
        result.put("loginUser", loginInfo);
        return result;
    }

    @Override
    public Map<String, Object> wechatLogin(Map<String, Object> map) {
        String code = (String) map.get("code");
        CarAssert.assertStrNotBlank(code,CodeEnum.DATA_ERROR);
        String accessUrl = WxConstants.GET_ACK_URL.replace("APPID",WxConstants.APPID)
                .replace("SECRET", WxConstants.SECRET).replace("CODE", code);
        String httpGet = HttpUtil.httpGet(accessUrl);
        JSONObject accessObject = JSONObject.parseObject(httpGet);
        String access_token = accessObject.getString("access_token");
        String openid = accessObject.getString("openid");
        //判断用户是不是第一次用微信登录
        List<UserWx> userWxes = wxMapper.selectList(new EntityWrapper<UserWx>().eq("openid", openid));
        if(userWxes != null && userWxes.size() > 0){
            //登录过，返回登录信息，直接免密码登录
            UserWx userWx = userWxes.get(0);
            LoginInfo loginInfo = loginInfoMapper.selectOneByUserId(userWx.getUserId());
            HashMap<String, Object> result = backLoginInfo(loginInfo);
            return result;
        }else {
            //否则将 access_token和openid返回给前端
            Map<String,Object> result = new HashMap<>();
            result.put("accessToken",access_token);
            result.put("openid",openid);
            result.put("isWechat",true);
            return result;
        }
    }
}
